/*
 * Copyright (c) 2021-2021, WeiStudio
 *
 * License: Apache-2.0
 *
 * Change Logs:
 * Date           Author        Notes
 * 2021-07-13     WeiStudio     the first version
 */



#ifndef __QE_DEF_H__
#define __QE_DEF_H__



#include "autoconfig.h"



/* Version */
#define QE_VERSION						1L					/**< major version number */
#define QE_SUBVERSION					1L					/**< minor version number */
#define QE_REVISION						0L					/**< revise version number */

#define QESF_VERSION                	((QE_VERSION * 10000) + \
                                         (QE_SUBVERSION * 100) + QE_REVISION)


#define QE_NULL                         (0)

typedef int								qe_bool_t;	   	/**< boolean type */

typedef signed   char                   qe_s8;      	/**<  8bit integer type */
typedef unsigned char                   qe_u8;     	/**<  8bit unsigned integer type */
typedef signed   short                  qe_s16;     	/**< 16bit integer type */
typedef unsigned short                  qe_u16;    	/**< 16bit unsigned integer type */
typedef signed   int                    qe_s32;     	/**< 32bit integer type */
typedef unsigned int                    qe_u32;    	/**< 32bit unsigned integer type */
typedef signed long long                qe_s64;     	/**< 64bit integer type */
typedef unsigned long long              qe_u64;    	/**< 64bit unsigned integer type */
typedef unsigned long                   qe_ubase_t;     	/**< Nbit unsigned CPU related data type */
typedef long                            qe_base_t;      	/**< Nbit CPU related date type */
typedef qe_ubase_t                      qe_size_t;      	/**< Type for size number */
typedef qe_base_t                       qe_off_t;       	/**< Type for offset */
typedef qe_ubase_t						qe_time_t;

#define qe_true							(1)
#define qe_false						(0)

#define QE_WAIT_FOREVER					(-1)



#define QE_BITS_PER_BYTE                8
#define QE_BYTES_PER_LONG               sizeof(unsigned long)
#define QE_BITS_PER_LONG                (QE_BITS_PER_BYTE*QE_BYTES_PER_LONG)
#define QE_LONG_POW                     5
#define QE_DIV_ROUND_UP(n,d)            (((n) + (d) - 1) / (d))
#define QE_BITS_WORD(bits)              ((bits) / QE_BITS_PER_LONG)
#define QE_BITS_TO_LONG(bits)           QE_DIV_ROUND_UP(bits, QE_BITS_PER_LONG)



/* error code definitions @{ */
typedef enum {

	qe_ok 			= 0,

	/* 1~10: special return value, means non-error */
	qe_finish,					/* for waiting areas */
	qe_unfinished,				/* for waiting areas */
	qe_yield,					/* need to exit from current function scope */
	qe_noneed,					/* don't need to do something */
	qe_reboot,					/* system reboot */
	qe_killed,					/* object be killed */
	qe_save,

	qe_err_common  	= 10,
	qe_err_oom,					/* out of memory */
	qe_err_oor,					/* out of range */
	qe_err_busy,				/* Resource busy */
    qe_err_timeout,
	qe_err_full,
	qe_err_empty,
	qe_err_nosys,
	qe_err_param,
	qe_err_exist,
	qe_err_notexist = 20,
	qe_err_incomplete,			/* data incomplete */
	qe_err_notfind,
	qe_err_notsupport,
    qe_err_notenough,
	qe_err_match,
	qe_err_send,
	qe_err_recv,
	qe_err_write,
	qe_err_read,
} qe_err_t;



/**
 * Compiler related macro definitions
 * 
 */
#define qe_section(x)           __attribute__((section(x)))
#define qe_unused               __attribute__((unused))
#define qe_used                 __attribute__((used))
#define qe_align(n)             __attribute__((aligned(n)))
#define qe_weak                 __attribute__((weak))
#define qe_inline               static __inline


/* 
 * @Space Stage Initialization @{
 */
typedef int (*init_fn_t)(void);
typedef int (*qe_initcall_t)(void);

#define qe_init                 __attribute__((section(".init.text")))
#define qe_initdata             __attribute__((section(".init.data")))

#define QE_EXPORT(fn, level) \
	static qe_initcall_t __qe_initcall_##fn qe_used\
		qe_section(".qe_initcall."level) = fn;

/* chip architecture initialization */
#define QE_ARCH_EXPORT(fn)				QE_EXPORT(fn, "1")

/* board init routines will be called in board_init() function */
#define QE_BOARD_EXPORT(fn)          	QE_EXPORT(fn, "2")

/* components pre-initialization (pure software initilization) */
#define QE_PREV_EXPORT(fn)            	QE_EXPORT(fn, "3")

/* device initialization */
#define QE_DEVICE_EXPORT(fn)          	QE_EXPORT(fn, "4")

/* components initialization (dfs, lwip, ...) */
#define QE_COMPONENT_EXPORT(fn)       	QE_EXPORT(fn, "5")

/* environment initialization (mount disk, ...) */
#define QE_ENV_EXPORT(fn)             	QE_EXPORT(fn, "6")

/* appliation initialization (application etc ...) */
#define QE_APP_EXPORT(fn)				QE_EXPORT(fn, "7")
/* @Space Stage Initialization }@ */


/* 
 * @Space Application version @{
 */
#define qe_version_string_make(x,y,z,d) 	#x"."#y"."#z" "d
#define qe_version_string_build(x,y,z,d)	qe_version_string_make(x,y,z,d)
#define qe_version_encode(x,y,z)		(qe_u32)(((x)<<16)|((y)<<8)|(z))

struct qe_app_version {
    qe_u8 major;
    qe_u8 minor;
    qe_u8 patch;
    qe_u8 flag;
    qe_u32 vcode;
    char string[16];
    char date[16];
    char time[16];
};
/* @Space Application version }@ */


/**
 * Double List structure
 */
struct qe_list_node {
    struct qe_list_node *next;                          /**< point to next node. */
    struct qe_list_node *prev;                          /**< point to prev node. */
};
typedef struct qe_list_node qe_list;               /**< Type for lists. */

/**
 * String Builder
 */
struct qe_str_builder {
	char *p;
	char *head;
	int   max;
	int   len;
};
typedef struct qe_str_builder qe_strb_t;

/** 
 * GenericBufffer(gbuf)
 */
struct qe_gbuf {
	void         *p;
	unsigned int dsize; 	/* data size */
	unsigned int nbytes;	/* memory size */
	unsigned int dynamic:1;
	unsigned int reserve_flags:31;
	qe_list    list;
};
typedef struct qe_gbuf qe_gbuf_t;

struct qe_gbuf_pool {
	unsigned int dsize; 	/* data size */
	unsigned int nbytes;	/* memory size */
	unsigned int num_bufs;
	qe_list    bufs;
};
typedef struct qe_gbuf_pool qe_gbuf_pool_t;

/**
 * RingBuffer
 */
struct qe_ringbuffer {
	char *buf;
	unsigned int head;
	unsigned int tail;
	unsigned int count;
	unsigned int length;
};
typedef struct qe_ringbuffer qe_ringbuffer_t;

/**
 * Min Priority Queue
 */
#define QE_MINPQ_F_CDC	0x0001
#define QE_MINPQ_F_RES	0x0002
struct qe_minpq {
	void *data;
	unsigned int *prio;
	unsigned int elem_size;
	unsigned int num_elems;
	unsigned int cnt_elems;
	unsigned int flags;
	qe_bool_t    (*comparator)(void *, void *);
};

typedef struct qe_minpq qe_workqueue_t;
struct qe_worker {
	void *data;
	qe_u32 call_ts;
	qe_err_t (*handle)(qe_workqueue_t *q, struct qe_worker *w);
};
typedef struct qe_worker qe_worker_t;

/* Queue */
#define QE_QUEUE_RING		0x00000001U		/* Ring queue */
#define QE_QUEUE_CREATE		0x00000100U		/* Queue is create use qe_queue_create() */
struct qe_queue {
	void *data;
	unsigned int head;
	unsigned int tail;
	unsigned int count;
	unsigned int elem_size;
	unsigned int num_elems;
	unsigned int flags;
};
typedef struct qe_queue qe_queue_t;

/* RingQueue */
struct qe_ringq {
    void *buf;
	unsigned int head;
	unsigned int tail;
	unsigned int count;
	unsigned int depth;
	unsigned int elem_size;
	unsigned int num_elems;
};

/* Bitmap */
#define qe_bitmap(name, bits) \
    unsigned long name[QE_BITS_TO_LONG(bits)]
#define QE_BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % QE_BITS_PER_LONG))
#define QE_BITMAP_LAST_WORD_MASK(nbits)					\
(									\
	((nbits) % QE_BITS_PER_LONG) ?					\
		(1UL<<((nbits) % QE_BITS_PER_LONG))-1 : ~0UL		\
)

typedef struct {
    unsigned int x;
    unsigned int y;
} qe_dim2;

typedef struct {
    unsigned int x;
    unsigned int y;
    unsigned int z;
} qe_dim3;

typedef struct {
    unsigned int x;
    unsigned int y;
	unsigned int w;
	unsigned int h;
} qe_box;

/* Workqueue */
struct qe_wq_work {
	void *data;
	qe_u32 call_ms;
	qe_err_t (*handle)(struct qe_minpq *wq, struct qe_wq_work *);
};

/**
 * @Space Device @{
 */

/**
 * device (I/O) class type
 */
enum qe_devclass_type {
	QE_DevClass_Char = 0,							/**< character device */
	QE_DevClass_Block,								/**< block device */
	QE_DevClass_NetIf,								/**< net interface */
	QE_DevClass_MTD,								/**< memory device */
	QE_DevClass_CAN,								/**< CAN device */
	QE_DevClass_RTC,								/**< RTC device */
	QE_DevClass_Sound,								/**< Sound device */
	QE_DevClass_Graphic,							/**< Graphic device */
	QE_DevClass_I2CBUS, 							/**< I2C bus device */
	QE_DevClass_USBDevice,							/**< USB slave device */
	QE_DevClass_USBHost,							/**< USB host bus */
	QE_DevClass_SPIBUS, 							/**< SPI bus device */
	QE_DevClass_SPIDevice,							/**< SPI device */
	QE_DevClass_SDIO,								/**< SDIO bus device */
	QE_DevClass_PM, 								/**< PM pseudo device */
	QE_DevClass_Pipe,								/**< Pipe device */
	QE_DevClass_Portal, 							/**< Portal device */
	QE_DevClass_Timer,								/**< Timer device */
	QE_DevClass_Miscellaneous,						/**< Miscellaneous device */
	QE_DevClass_Sensor, 							/**< Sensor device */
	QE_DevClass_ImgSensor,							/**< Image Sensor device */
	QE_DevClass_Touch,								/**< Touch device */
	QE_DevClass_PHY,								/**< PHY device */
	QE_DevClass_Unknown 							/**< unknown device */
};

/**
 * device flags defitions
 */
#define QE_DEV_F_DEACTIVATE       0x000           /**< device is not not initialized */

#define QE_DEV_F_RDONLY           0x001           /**< read only */
#define QE_DEV_F_WRONLY           0x002           /**< write only */
#define QE_DEV_F_RDWR             0x003           /**< read and write */

#define QE_DEV_F_REMOVABLE        0x004           /**< removable device */
#define QE_DEV_F_STANDALONE       0x008           /**< standalone device */
#define QE_DEV_F_ACTIVATED        0x010           /**< device is activated */
#define QE_DEV_F_SUSPENDED        0x020           /**< device is suspended */
#define QE_DEV_F_STREAM           0x040           /**< stream mode */

#define QE_DEV_F_INT_RX           0x100           /**< INT mode on Rx */
#define QE_DEV_F_DMA_RX           0x200           /**< DMA mode on Rx */
#define QE_DEV_F_INT_TX           0x400           /**< INT mode on Tx */
#define QE_DEV_F_DMA_TX           0x800           /**< DMA mode on Tx */

#define QE_DEV_OF_CLOSE           0x000           /**< device is closed */
#define QE_DEV_OF_OPEN            0x008           /**< device is opened */
#define QE_DEV_OF_MASK            0xf0f           /**< mask of open flag */

#define QE_DEV_CTRL_RESUME        0x01            /**< resume device */
#define QE_DEV_CTRL_SUSPEND       0x02            /**< suspend device */
#define QE_DEV_CTRL_CONFIG        0x03            /**< configure device */
#define QE_DEV_CTRL_CLOSE         0x04            /**< close device */
#define QE_DEV_CTRL_GET_NAME	  0x05
#define QE_DEV_CTRL_SET_NAME	  0X06

#define QE_DEV_CTRL_SET_INT       0x10            /**< set interrupt */
#define QE_DEV_CTRL_CLR_INT       0x11            /**< clear interrupt */
#define QE_DEV_CTRL_GET_INT       0x12            /**< get interrupt status */


typedef struct qe_device * qe_device_t;

/**
 * operations set for device object
 */
struct qe_device_ops {
    /* common device interface */
    qe_err_t   (*init)   (qe_device_t dev);
    qe_err_t   (*open)   (qe_device_t dev, qe_u16 oflag);
    qe_err_t   (*close)  (qe_device_t dev);
    qe_size_t  (*read)   (qe_device_t dev, qe_off_t pos, void *buffer, qe_size_t size);
    qe_size_t  (*write)  (qe_device_t dev, qe_off_t pos, const void *buffer, qe_size_t size);
    qe_err_t   (*control)(qe_device_t dev, int cmd, void *args);
};

/**
 * Device structure
 */
struct qe_device {

	enum qe_devclass_type class;

	char name[8];

	qe_u16 flag;
	qe_u16 open_flag;

	qe_u16 reference;

	qe_u16 device_id;

	/* device callback */
	qe_err_t (*rx_indicate)(qe_device_t dev, qe_size_t size);
	qe_err_t (*tx_complete)(qe_device_t dev, void *buffer);

	const struct qe_device_ops *ops;

	/* private data */
	void *private;

	/* register to device list */
	qe_list list;
};

#endif /* __QE_DEF_H__ */
